home *** CD-ROM | disk | FTP | other *** search
/ Mac Easy 2010 May / Mac Life Ubuntu.iso / casper / filesystem.squashfs / usr / src / linux-headers-2.6.28-15 / arch / sparc / include / asm / system_32.h < prev    next >
Encoding:
C/C++ Source or Header  |  2008-12-24  |  8.1 KB  |  284 lines

  1. #ifndef __SPARC_SYSTEM_H
  2. #define __SPARC_SYSTEM_H
  3.  
  4. #include <linux/kernel.h>
  5. #include <linux/threads.h>    /* NR_CPUS */
  6. #include <linux/thread_info.h>
  7.  
  8. #include <asm/page.h>
  9. #include <asm/psr.h>
  10. #include <asm/ptrace.h>
  11. #include <asm/btfixup.h>
  12. #include <asm/smp.h>
  13.  
  14. #ifndef __ASSEMBLY__
  15.  
  16. #include <linux/irqflags.h>
  17.  
  18. /*
  19.  * Sparc (general) CPU types
  20.  */
  21. enum sparc_cpu {
  22.   sun4        = 0x00,
  23.   sun4c       = 0x01,
  24.   sun4m       = 0x02,
  25.   sun4d       = 0x03,
  26.   sun4e       = 0x04,
  27.   sun4u       = 0x05, /* V8 ploos ploos */
  28.   sun_unknown = 0x06,
  29.   ap1000      = 0x07, /* almost a sun4m */
  30. };
  31.  
  32. /* Really, userland should not be looking at any of this... */
  33. #ifdef __KERNEL__
  34.  
  35. extern enum sparc_cpu sparc_cpu_model;
  36.  
  37. #define ARCH_SUN4C (sparc_cpu_model==sun4c)
  38.  
  39. #define SUN4M_NCPUS            4              /* Architectural limit of sun4m. */
  40.  
  41. extern char reboot_command[];
  42.  
  43. extern struct thread_info *current_set[NR_CPUS];
  44.  
  45. extern unsigned long empty_bad_page;
  46. extern unsigned long empty_bad_page_table;
  47. extern unsigned long empty_zero_page;
  48.  
  49. extern void sun_do_break(void);
  50. extern int serial_console;
  51. extern int stop_a_enabled;
  52. extern int scons_pwroff;
  53.  
  54. static inline int con_is_present(void)
  55. {
  56.     return serial_console ? 0 : 1;
  57. }
  58.  
  59. /* When a context switch happens we must flush all user windows so that
  60.  * the windows of the current process are flushed onto its stack. This
  61.  * way the windows are all clean for the next process and the stack
  62.  * frames are up to date.
  63.  */
  64. extern void flush_user_windows(void);
  65. extern void kill_user_windows(void);
  66. extern void synchronize_user_stack(void);
  67. extern void fpsave(unsigned long *fpregs, unsigned long *fsr,
  68.            void *fpqueue, unsigned long *fpqdepth);
  69.  
  70. #ifdef CONFIG_SMP
  71. #define SWITCH_ENTER(prv) \
  72.     do {            \
  73.     if (test_tsk_thread_flag(prv, TIF_USEDFPU)) { \
  74.         put_psr(get_psr() | PSR_EF); \
  75.         fpsave(&(prv)->thread.float_regs[0], &(prv)->thread.fsr, \
  76.                &(prv)->thread.fpqueue[0], &(prv)->thread.fpqdepth); \
  77.         clear_tsk_thread_flag(prv, TIF_USEDFPU); \
  78.         (prv)->thread.kregs->psr &= ~PSR_EF; \
  79.     } \
  80.     } while(0)
  81.  
  82. #define SWITCH_DO_LAZY_FPU(next)    /* */
  83. #else
  84. #define SWITCH_ENTER(prv)        /* */
  85. #define SWITCH_DO_LAZY_FPU(nxt)    \
  86.     do {            \
  87.     if (last_task_used_math != (nxt))        \
  88.         (nxt)->thread.kregs->psr&=~PSR_EF;    \
  89.     } while(0)
  90. #endif
  91.  
  92. extern void flushw_all(void);
  93.  
  94. /*
  95.  * Flush windows so that the VM switch which follows
  96.  * would not pull the stack from under us.
  97.  *
  98.  * SWITCH_ENTER and SWITH_DO_LAZY_FPU do not work yet (e.g. SMP does not work)
  99.  * XXX WTF is the above comment? Found in late teen 2.4.x.
  100.  */
  101. #define prepare_arch_switch(next) do { \
  102.     __asm__ __volatile__( \
  103.     ".globl\tflush_patch_switch\nflush_patch_switch:\n\t" \
  104.     "save %sp, -0x40, %sp; save %sp, -0x40, %sp; save %sp, -0x40, %sp\n\t" \
  105.     "save %sp, -0x40, %sp; save %sp, -0x40, %sp; save %sp, -0x40, %sp\n\t" \
  106.     "save %sp, -0x40, %sp\n\t" \
  107.     "restore; restore; restore; restore; restore; restore; restore"); \
  108. } while(0)
  109.  
  110.     /* Much care has gone into this code, do not touch it.
  111.      *
  112.      * We need to loadup regs l0/l1 for the newly forked child
  113.      * case because the trap return path relies on those registers
  114.      * holding certain values, gcc is told that they are clobbered.
  115.      * Gcc needs registers for 3 values in and 1 value out, so we
  116.      * clobber every non-fixed-usage register besides l2/l3/o4/o5.  -DaveM
  117.      *
  118.      * Hey Dave, that do not touch sign is too much of an incentive
  119.      * - Anton & Pete
  120.      */
  121. #define switch_to(prev, next, last) do {                        \
  122.     SWITCH_ENTER(prev);                                \
  123.     SWITCH_DO_LAZY_FPU(next);                            \
  124.     cpu_set(smp_processor_id(), next->active_mm->cpu_vm_mask);            \
  125.     __asm__ __volatile__(                                \
  126.     "sethi    %%hi(here - 0x8), %%o7\n\t"                        \
  127.     "mov    %%g6, %%g3\n\t"                                \
  128.     "or    %%o7, %%lo(here - 0x8), %%o7\n\t"                    \
  129.     "rd    %%psr, %%g4\n\t"                            \
  130.     "std    %%sp, [%%g6 + %4]\n\t"                            \
  131.     "rd    %%wim, %%g5\n\t"                            \
  132.     "wr    %%g4, 0x20, %%psr\n\t"                            \
  133.     "nop\n\t"                                    \
  134.     "std    %%g4, [%%g6 + %3]\n\t"                            \
  135.     "ldd    [%2 + %3], %%g4\n\t"                            \
  136.     "mov    %2, %%g6\n\t"                                \
  137.     ".globl    patchme_store_new_current\n"                        \
  138. "patchme_store_new_current:\n\t"                            \
  139.     "st    %2, [%1]\n\t"                                \
  140.     "wr    %%g4, 0x20, %%psr\n\t"                            \
  141.     "nop\n\t"                                    \
  142.     "nop\n\t"                                    \
  143.     "nop\n\t"    /* LEON needs all 3 nops: load to %sp depends on CWP. */        \
  144.     "ldd    [%%g6 + %4], %%sp\n\t"                            \
  145.     "wr    %%g5, 0x0, %%wim\n\t"                            \
  146.     "ldd    [%%sp + 0x00], %%l0\n\t"                        \
  147.     "ldd    [%%sp + 0x38], %%i6\n\t"                        \
  148.     "wr    %%g4, 0x0, %%psr\n\t"                            \
  149.     "nop\n\t"                                    \
  150.     "nop\n\t"                                    \
  151.     "jmpl    %%o7 + 0x8, %%g0\n\t"                            \
  152.     " ld    [%%g3 + %5], %0\n\t"                            \
  153.     "here:\n"                                    \
  154.         : "=&r" (last)                                    \
  155.         : "r" (&(current_set[hard_smp_processor_id()])),    \
  156.       "r" (task_thread_info(next)),                \
  157.       "i" (TI_KPSR),                    \
  158.       "i" (TI_KSP),                        \
  159.       "i" (TI_TASK)                        \
  160.     :       "g1", "g2", "g3", "g4", "g5",       "g7",    \
  161.       "l0", "l1",       "l3", "l4", "l5", "l6", "l7",    \
  162.       "i0", "i1", "i2", "i3", "i4", "i5",            \
  163.       "o0", "o1", "o2", "o3",                   "o7");    \
  164.     } while(0)
  165.  
  166. /* XXX Change this if we ever use a PSO mode kernel. */
  167. #define mb()    __asm__ __volatile__ ("" : : : "memory")
  168. #define rmb()    mb()
  169. #define wmb()    mb()
  170. #define read_barrier_depends()    do { } while(0)
  171. #define set_mb(__var, __value)  do { __var = __value; mb(); } while(0)
  172. #define smp_mb()    __asm__ __volatile__("":::"memory")
  173. #define smp_rmb()    __asm__ __volatile__("":::"memory")
  174. #define smp_wmb()    __asm__ __volatile__("":::"memory")
  175. #define smp_read_barrier_depends()    do { } while(0)
  176.  
  177. #define nop() __asm__ __volatile__ ("nop")
  178.  
  179. /* This has special calling conventions */
  180. #ifndef CONFIG_SMP
  181. BTFIXUPDEF_CALL(void, ___xchg32, void)
  182. #endif
  183.  
  184. static inline unsigned long xchg_u32(__volatile__ unsigned long *m, unsigned long val)
  185. {
  186. #ifdef CONFIG_SMP
  187.     __asm__ __volatile__("swap [%2], %0"
  188.                  : "=&r" (val)
  189.                  : "0" (val), "r" (m)
  190.                  : "memory");
  191.     return val;
  192. #else
  193.     register unsigned long *ptr asm("g1");
  194.     register unsigned long ret asm("g2");
  195.  
  196.     ptr = (unsigned long *) m;
  197.     ret = val;
  198.  
  199.     /* Note: this is magic and the nop there is
  200.        really needed. */
  201.     __asm__ __volatile__(
  202.     "mov    %%o7, %%g4\n\t"
  203.     "call    ___f____xchg32\n\t"
  204.     " nop\n\t"
  205.     : "=&r" (ret)
  206.     : "0" (ret), "r" (ptr)
  207.     : "g3", "g4", "g7", "memory", "cc");
  208.  
  209.     return ret;
  210. #endif
  211. }
  212.  
  213. #define xchg(ptr,x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
  214.  
  215. extern void __xchg_called_with_bad_pointer(void);
  216.  
  217. static inline unsigned long __xchg(unsigned long x, __volatile__ void * ptr, int size)
  218. {
  219.     switch (size) {
  220.     case 4:
  221.         return xchg_u32(ptr, x);
  222.     };
  223.     __xchg_called_with_bad_pointer();
  224.     return x;
  225. }
  226.  
  227. /* Emulate cmpxchg() the same way we emulate atomics,
  228.  * by hashing the object address and indexing into an array
  229.  * of spinlocks to get a bit of performance...
  230.  *
  231.  * See arch/sparc/lib/atomic32.c for implementation.
  232.  *
  233.  * Cribbed from <asm-parisc/atomic.h>
  234.  */
  235. #define __HAVE_ARCH_CMPXCHG    1
  236.  
  237. /* bug catcher for when unsupported size is used - won't link */
  238. extern void __cmpxchg_called_with_bad_pointer(void);
  239. /* we only need to support cmpxchg of a u32 on sparc */
  240. extern unsigned long __cmpxchg_u32(volatile u32 *m, u32 old, u32 new_);
  241.  
  242. /* don't worry...optimizer will get rid of most of this */
  243. static inline unsigned long
  244. __cmpxchg(volatile void *ptr, unsigned long old, unsigned long new_, int size)
  245. {
  246.     switch (size) {
  247.     case 4:
  248.         return __cmpxchg_u32((u32 *)ptr, (u32)old, (u32)new_);
  249.     default:
  250.         __cmpxchg_called_with_bad_pointer();
  251.         break;
  252.     }
  253.     return old;
  254. }
  255.  
  256. #define cmpxchg(ptr, o, n)                        \
  257. ({                                    \
  258.     __typeof__(*(ptr)) _o_ = (o);                    \
  259.     __typeof__(*(ptr)) _n_ = (n);                    \
  260.     (__typeof__(*(ptr))) __cmpxchg((ptr), (unsigned long)_o_,    \
  261.             (unsigned long)_n_, sizeof(*(ptr)));        \
  262. })
  263.  
  264. #include <asm-generic/cmpxchg-local.h>
  265.  
  266. /*
  267.  * cmpxchg_local and cmpxchg64_local are atomic wrt current CPU. Always make
  268.  * them available.
  269.  */
  270. #define cmpxchg_local(ptr, o, n)                             \
  271.     ((__typeof__(*(ptr)))__cmpxchg_local_generic((ptr), (unsigned long)(o),\
  272.             (unsigned long)(n), sizeof(*(ptr))))
  273. #define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n))
  274.  
  275. extern void die_if_kernel(char *str, struct pt_regs *regs) __attribute__ ((noreturn));
  276.  
  277. #endif /* __KERNEL__ */
  278.  
  279. #endif /* __ASSEMBLY__ */
  280.  
  281. #define arch_align_stack(x) (x)
  282.  
  283. #endif /* !(__SPARC_SYSTEM_H) */
  284.